home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / Apps / DevTools / eText5 / Source / eTAudio.subproj / eTAudioUI.m < prev    next >
Encoding:
Text File  |  1994-12-23  |  8.1 KB  |  313 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //    FILENAME:    eTAudioUI.m 
  3. //    SUMMARY:    User Interface for Audio annotations to eText documents
  4. //    SUPERCLASS:    eTAudioUI:eTImageUI:Object
  5. //    INTERFACE:    None
  6. //    PROTOCOLS:    <Inspectable>
  7. //    AUTHOR:        Rohit Khare
  8. //    COPYRIGHT:    (c) 1994 California Institure of Technology, eText Project
  9. ///////////////////////////////////////////////////////////////////////////////
  10. //    IMPLEMENTATION COMMENTS
  11. //        watch for hacks vis a vis sound display, play loops, and meters.
  12. ///////////////////////////////////////////////////////////////////////////////
  13. //    HISTORY
  14. //    07/24/94:    Rearchitected for PR1/eTImage
  15. //    01/24/94:    Created. Derived largely from Version3's temporary Hypertext
  16. //                '93 hack. Renamed as eTAudio and aTAudioUI.
  17. ///////////////////////////////////////////////////////////////////////////////
  18.  
  19. #import "eTAudioUI.h"
  20.  
  21. @implementation eTAudioUI
  22. //    id    audioPanel;
  23. //    id    audioView;
  24. //    id    etAudio;
  25. //    id    nameField;
  26. //    id    eraseButton;
  27. //    id    pauseButton;
  28. //    id    playButton;
  29. //    id    recordButton;
  30. //    id    stopButton;
  31. //    id    soundMeter;
  32. //    id    soundView;
  33.  
  34. - setAnnotation:newAudio
  35. {    
  36.     id theSound;
  37.     
  38.     if (etAudio == newAudio) return self;
  39.     [super setAnnotation:newAudio];    // this is an awkward naming of the "chain" 
  40.  
  41.     // properly unload the old audio
  42.     [soundMeter stop:self];
  43.     [soundMeter setSound:nil];
  44.     [soundView stop:self];
  45.     [[soundView sound] setDelegate:nil];
  46.     if ([etAudio respondsTo:@selector(audioEnded)])
  47.         [etAudio audioEnded];
  48.     
  49.     etAudio = newAudio;
  50.     [nameField setStringValue:[etAudio audioName]];
  51.     [playButton setState:0];
  52.     [pauseButton setState:0];
  53.     [stopButton setState:0];
  54.     [recordButton setState:0];
  55.     theSound = [etAudio sound];
  56.     [soundView setSound:theSound];
  57.     [theSound setDelegate:self];
  58.     [soundView setDelegate:self];        // redundant, but hey...
  59.     [soundMeter setSound:theSound];
  60. //    There ought to be a link switch somewhere on that damn panel...
  61. //    [linkSwitch setState:[etAudio isAudioLinked];
  62.     return self;
  63. }
  64.  
  65. - soundView {return soundView;}
  66. - soundMeter {return soundMeter;}
  67. ///////////////////////////////////
  68. + new
  69. {
  70.     static eTAudioUI *ui = nil;
  71.     
  72.     if (!ui) {
  73.         ui = [[eTAudioUI alloc] init];
  74.     }
  75.     return ui;
  76. }
  77. - init
  78. {
  79.     char        buf[MAXPATHLEN];
  80.     NXBundle   *bundle;
  81.  
  82.     [super init];
  83.     bundle = [NXBundle bundleForClass:[self class]];
  84.     if ( [bundle getPath:buf forResource:"eTAudioUI" ofType:"nib"] ) {
  85.         [NXApp loadNibFile:buf owner:self withNames:NO];
  86.     } else {
  87.         NXLogError("NIB not found: eTAudioUI");
  88.     }
  89.     audioView = [audioPanel contentView];
  90.     return self;
  91. }
  92. - free {return self;}
  93.  
  94. ///////////////////////////////////
  95. #define PROP "Audio Properties"
  96. - (const NXAtom *) types
  97. {
  98.     static NXAtom *types = NULL;
  99.     
  100.     if (!types) {
  101.         int i;
  102.         const NXAtom *superTypes = [super types];
  103.         
  104.         for(i=0;superTypes[i];i++);
  105.         i++; // make room for terminating NULL
  106.         i++; // make room for our type
  107.         types = malloc(i * sizeof(NXAtom));
  108.         types[0] = NXUniqueString(PROP);
  109.         for(i=0;superTypes[i];i++) types[i+1] = superTypes[i];
  110.         types[i+1] = NULL;
  111.     }
  112.     return types;
  113. }
  114. - (const char *) inspectorTitle
  115. {
  116.     return NXUniqueString("Audio");
  117. }
  118. - resignInspector: (View *) oldInspector ofType: (const char *) type
  119. {
  120.     if (oldInspector == audioView) {
  121.         [soundMeter stop:self];
  122.         [soundView resignFirstResponder];
  123.         [audioView removeFromSuperview];    // keep it attached to some window
  124.         [audioPanel setContentView:audioView];
  125.     } else 
  126.         [super resignInspector:oldInspector ofType:type];
  127.     return self;
  128. }
  129. - activateInspector: (View *) newInspector ofType: (const char *) type
  130. {
  131.     if (newInspector == audioView) {
  132.         //anything special here?
  133.         switch ([[soundView soundBeingProcessed] status]) {
  134.             case NX_SoundPlayingPaused:
  135.             case NX_SoundRecordingPaused:
  136.             case NX_SoundPlaying:
  137.             case NX_SoundRecording:            [soundMeter run:self]; break;
  138.         }
  139.         [soundView setEditable:[etAudio isAudioMutable]];
  140.         [nameField setEditable:[etAudio isAudioMutable]];
  141.     } else 
  142.         [super activateInspector:newInspector ofType:type];
  143.     return self;
  144. }
  145. - inspectorForType:(const char *) type
  146. {
  147.     if(!strcmp(type,NXUniqueString(PROP)))
  148.         return audioView;
  149.     return [super inspectorForType:type];
  150. }
  151.  
  152. ///////////////////////////////////
  153. - editName:sender
  154. {
  155.     [etAudio setAudioName:[sender stringValue]];
  156.     return self;
  157. }
  158.  
  159. - erase:sender
  160. {
  161.     if (![etAudio isAudioMutable]) {
  162.         NXRunAlertPanel( "eTAudio",
  163.         "You cannot modify the sound file %s. Try copying it "
  164.         "directly if you need to edit it.", NULL, NULL, NULL,
  165.         [etAudio audioName]);
  166.         return self;
  167.     }
  168.     [soundView stop:self];
  169.     [soundMeter stop:self];
  170.     if ([etAudio respondsTo:@selector(audioEnded)])
  171.         [etAudio audioEnded];
  172.     [soundView setSelection:0 size:[[etAudio sound] sampleCount]];
  173.     [soundView delete:self];
  174.     [playButton setState:0];
  175.     [recordButton setState:0];
  176.     [pauseButton setState:0];
  177.     [[audioView window] display];
  178.     return self;
  179. }
  180.  
  181. - pause:sender
  182. {
  183.      switch ([[soundView soundBeingProcessed] status]) {
  184.         case NX_SoundPlaying:
  185.         case NX_SoundRecording:            
  186.             [soundView pause:self]; 
  187.             if ([etAudio respondsTo:@selector(audioPaused)])
  188.                 [etAudio audioPaused];
  189.             break;
  190.         case NX_SoundPlayingPaused:
  191.         case NX_SoundRecordingPaused:
  192.             [soundView resume:self]; 
  193.             if ([etAudio respondsTo:@selector(audioResumed)])
  194.                 [etAudio audioResumed];
  195.             break;
  196.         default:                        [pauseButton setState:0];
  197.     }
  198.     return self;
  199. }
  200.  
  201. - play:sender
  202. {
  203.     if ([[soundView soundBeingProcessed] status] == NX_SoundPlaying) {
  204.         [self stop:sender];
  205.         return self;
  206.     }
  207.     if( [[soundView soundBeingProcessed] duration]== 0.0) {
  208.         [playButton setState:0];
  209.         if ([etAudio respondsTo:@selector(audioEnded)])
  210.             [etAudio audioEnded];
  211.         return self;
  212.     }
  213.     [recordButton setState:0];
  214.     [pauseButton setState:0];
  215.     [soundView play:self];
  216.     [soundMeter setSound:[soundView soundBeingProcessed]];
  217.     if ([soundMeter window]) [soundMeter run:self];
  218.     if ([etAudio respondsTo:@selector(audioStarted)])
  219.         [etAudio audioStarted];
  220.     return self;
  221. }
  222.  
  223. - record:sender
  224. {
  225.     if (![etAudio isAudioMutable]) {
  226.         NXRunAlertPanel( "eTAudio",
  227.         "You cannot modify the sound file %s. Try copying "
  228.         "it directly if you need to edit it.", NULL, NULL, NULL,
  229.         [etAudio audioName]);
  230.         [recordButton setState:0];
  231.         if ([etAudio respondsTo:@selector(audioEnded)])
  232.             [etAudio audioEnded];
  233.         return nil;
  234.     }
  235.     if ([[soundView soundBeingProcessed] status] == NX_SoundRecording) {
  236.         [self stop:sender];
  237.         return self;
  238.     }
  239.     [playButton setState:0];
  240.     [pauseButton setState:0];
  241.     [soundView record:self];
  242.     [soundMeter setSound:[soundView soundBeingProcessed]];
  243.     [soundMeter run:self];
  244.     if ([etAudio respondsTo:@selector(audioStarted)])
  245.         [etAudio audioStarted];
  246.     return self;
  247. }
  248.  
  249. - stop:sender
  250. {
  251.     [playButton setState:0];
  252.     [recordButton setState:0];
  253.     [pauseButton setState:0];
  254.     [soundView stop:self];
  255.     [audioView display];
  256.     [soundMeter stop:self];
  257.     if ([etAudio respondsTo:@selector(audioEnded)])
  258.         [etAudio audioEnded];
  259.     return self;
  260. }
  261. - didPlay:sender {
  262.     [soundMeter stop:self];
  263.     [playButton setState:0];
  264.     [recordButton setState:0];
  265.     [pauseButton setState:0];
  266.     [[audioView window] display];
  267.     if ([etAudio respondsTo:@selector(audioEnded)])
  268.         [etAudio audioEnded];
  269.     return self;
  270. }
  271. - didRecord:sender {
  272.     [soundMeter stop:self];
  273.     [playButton setState:0];
  274.     [recordButton setState:0];
  275.     [pauseButton setState:0];
  276.     if ([etAudio respondsTo:@selector(audioEnded)])
  277.         [etAudio audioEnded];
  278.     return self;
  279. }
  280. - hadError:sender {return [stopButton performClick:self];}
  281. - soundDidChange:sender {return [[etAudio etDoc] touch];}
  282. /////////////////////////////////
  283. - click:sender
  284. {
  285.     if (sender != etAudio) return nil;
  286.     if (![soundView soundBeingProcessed])
  287.         [soundView setSound:[etAudio sound]];
  288.     switch ([soundView soundBeingProcessed] ?
  289.             [[soundView soundBeingProcessed] status] :
  290.             [[soundView sound] status]) {
  291.         case NX_SoundStopped:        [playButton performClick:sender]; break;
  292.         case NX_SoundPlayingPaused:
  293.         case NX_SoundRecordingPaused:
  294.         case NX_SoundPlaying:
  295.         case NX_SoundRecording:        [pauseButton performClick:sender]; break;
  296.     }
  297.     return self;
  298. }
  299.  
  300. - doubleClick:sender 
  301. {
  302.     if (sender != etAudio) return nil;
  303.     return [stopButton performClick:self];
  304. }
  305. @end
  306. @interface eTSoundMeter:SoundMeter
  307. {}
  308. - drawCurrentValue;
  309. @end
  310. @implementation eTSoundMeter
  311. - drawCurrentValue{if (window) return [super drawCurrentValue]; return self;}
  312. @end
  313.